package mk.finki.chemistry.dice.grid;

import static mk.finki.chemistry.dice.DiceGAConstants.CHARGE_MAX;
import static mk.finki.chemistry.dice.DiceGAConstants.CHARGE_MIN;
import static mk.finki.chemistry.dice.DiceGAConstants.EPSILON_MAX;
import static mk.finki.chemistry.dice.DiceGAConstants.EPSILON_MIN;
import static mk.finki.chemistry.dice.DiceGAConstants.POPULATION_SIZE;
import static mk.finki.chemistry.dice.DiceGAConstants.SIGMA_MAX;
import static mk.finki.chemistry.dice.DiceGAConstants.SIGMA_MIN;
import mk.finki.chemistry.dice.Chromosome;
import mk.finki.chemistry.dice.DiceConfiguration;
import mk.finki.chemistry.dice.DiceGridFitnessFunction;

import org.homedns.dade.jcgrid.client.GridNodeClientConfig;
import org.jgap.Configuration;
import org.jgap.Gene;
import org.jgap.distr.grid.GridConfigurationBase;
import org.jgap.event.EventManager;
import org.jgap.impl.DoubleGene;

/**
 * Main configuration for defining the problem and the way it is solved in the
 * grid. Thus, the most important class in a JGAP Grid!
 */
public class GridConfiguration extends GridConfigurationBase {

	private static final long serialVersionUID = 2321721970353492565L;

	public void initialize(GridNodeClientConfig gridconfig) throws Exception {
		// Create the problem to be solved.
		gridconfig.setSessionName("DICE_thermalization_and_simulation");
		Configuration config = new DiceConfiguration();
		config.setEventManager(new EventManager());
		config.setPopulationSize(POPULATION_SIZE);
		config.setKeepPopulationSizeConstant(true);
		config.setFitnessFunction(new DiceGridFitnessFunction());

		Gene q = new DoubleGene(config, CHARGE_MIN, CHARGE_MAX);
		Gene epsilonC = new DoubleGene(config, EPSILON_MIN, EPSILON_MAX);
		Gene sigmaC = new DoubleGene(config, SIGMA_MIN, SIGMA_MAX);
		Gene epsilonCl = new DoubleGene(config, EPSILON_MIN, EPSILON_MAX);
		Gene sigmaCl = new DoubleGene(config, SIGMA_MIN, SIGMA_MAX);

		Gene[] sampleGenes = new Gene[5];
		sampleGenes[0] = q;
		sampleGenes[1] = epsilonC;
		sampleGenes[2] = sigmaC;
		sampleGenes[3] = epsilonCl;
		sampleGenes[4] = sigmaCl;

		config.setSampleChromosome(new Chromosome(config, sampleGenes));

		// Setup parameters.
		setWorkerReturnStrategy(new MyWorkerReturnStrategy());

		// No initialization of Genotype on behalf of workers.
		setGenotypeInitializer(null);

		// Evolution takes place on client only!
		setWorkerEvolveStrategy(null);

		// Setup the client to produce a work request for each chromosome
		// to get its fitness value computed by a single worker.
		setRequestSplitStrategy(new MyRequestSplitStrategy(config));
		setConfiguration(config);

		// Evolution takes place on client.
		setClientEvolveStrategy(new ClientEvolveStrategy());

		// Register client feedback listener.
		setClientFeedback(new MyClientFeedback());
	}

	public void validate() throws Exception {
		if (getRequestSplitStrategy() == null) {
			throw new RuntimeException("Please set the request split strategy first!");
		}
		if (getConfiguration() == null) {
			throw new RuntimeException("Please set the configuration first!");
		}
	}
}
